# -*- coding:utf8 -*-
import json
from django.conf.urls import url
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect

import time
import datetime
import os
import hashlib
from django.template import RequestContext
from wanbatvcom.http.decorators import require_params

from wanbatvcom.http.whttp import send_ok_response_with_data, send_error_response_with_message, \
    send_response_with_result, send_ok_response_with_list, send_error_response_on_exception
from wanplus import config
from wanbatvcom import utils
from wanplus.utils import ReleaseStatus
from wanplus.wangwangba.views import dogtv_load_covers

from wanplus.wangwangba.models import WangwangbaDogtvProgram

__author__ = 'Forcs'

CONTENT_STATE_NO_SYNC = ReleaseStatus.NONE
CONTENT_STATE_PREVIEW = ReleaseStatus.PREVIEW
CONTENT_STATE_RELEASE = ReleaseStatus.RELEASE

CONTENT_TYPE_VIDEO = "1"
CONTENT_TYPE_P = "2"
CONTENT_TYPE_SALE = "3"

DEFAULT_CATEGORY_CODE = 'C0000'
RECOMMEND_CATEGORY_CODE = 'C0003'


class WangwangbaContentService(object):

    def __init__(self, name=None):
        self._name = name if name else 'wwb'
        self._views_root = config.BASE_PATH + 'wangwangba/'
        self._views_name_prefix = 'cs'
        self._category_list = []

        from wanplus.wangwangba.models import WangwangbaCategory
        try:
            category_qs = WangwangbaCategory.objects.all()
            if category_qs.count():
                for item in category_qs:
                    self._category_list.append(item)
        except Exception as e:
            pass

        if not len(self._category_list):
            try:
                obj, create = WangwangbaCategory.objects.get_or_create(code=DEFAULT_CATEGORY_CODE)
                self._category_list.append(obj)
            except Exception as e:
                pass

    @property
    def urls(self):

        def views_name(name):
            return '%s_%s' % (self._name, name)

        urlpatterns = [
            url(r'^index$', self.index_views, name=views_name("index")),
            url(r'^category$', self.category_views, name=views_name("category")),
            url(r'^category/editor$', self.category_editor_views, name=views_name("category_editor")),

            url(r'^layout$', self.layout_views, name=views_name("layout")),
            url(r'^layout/list$', self.get_layout_list, name=views_name("get_layout_list")),
            url(r'^layout/save$', self.save_layout, name=views_name("save_layout")),
            url(r'^layout/preview/(?P<content_token>\w+)$', self.sync_content_preview,
                name=views_name("sync_content_preview")),
            url(r'^layout/release/(?P<content_token>\w+)$', self.sync_content_release,
                name=views_name("sync_content_release")),

            url(r'^recommend$', self.recommend_views, name=views_name("recommend")),
            url(r'^recommend/list$', self.recommend_list),

            url(r'^content$', self.content_views, name=views_name("content")),
            url(r'^content/editor$', self.content_editor_views, name=views_name("content_editor")),
            url(r'^content/cover/save$', self.save_content_cover, name=views_name("save_content_cover")),
            url(r'^content/video/save$', self.save_content_video, name=views_name("save_content_video")),
            url(r'^content/image/save$', self.save_content_image, name=views_name("save_content_image")),
            url(r'^content/list$', self.get_content_list, name=views_name("get_content_list")),
            url(r'^content/save$', self.save_content, name=views_name("save_content")),

            url(r'^dogtv$', self.dogtv_view, name=views_name("dogtv")),
            url(r'^dogtv/covers/load', dogtv_load_covers, name=views_name("dogtv_load_covers")),
            url(r'^dogtv/cover/save/(?P<position>\d+)$', self.save_dogtv_cover),
            url(r'^dogtv/cover/sync$', self.dogtv_sync_cover_to_api),
            url(r'^dogtv/programs$', self.get_dogtv_program_list, name=views_name('dogtv_program_list')),

            url(r'^journal/save$', self.save_journal, name=views_name('save_journal')),
            url(r'^journal/preview/(?P<journal_token>\w+)$', self.sync_journal_preview,
                name=views_name('sync_journal_preview')),
            url(r'^journal/release/(?P<journal_token>\w+)$', self.sync_journal_release,
                name=views_name('sync_journal_release')),

            url(r'^trailer$', self.trailer_views, name=views_name('trailer')),
            url(r'^trailer/info', self.get_trailer_info, name=views_name('trailer_info')),
            url(r'^trailer/preview$', self.sync_trailer_preview, name=views_name('trailer_preview')),
            url(r'^trailer/release$', self.sync_trailer_release, name=views_name('trailer_release')),
            url(r'^trailer/cover', self.save_trailer_cover, name=views_name('trailer_cover')),
            url(r'^encrypturl$', self.encrypt_url, name=views_name('encrypt_url'))

        ]
        return urlpatterns

    def get_views_name(self, name, prefix=None):
        if not prefix:
            prefix = self._views_name_prefix
        vn = '%s_%s' % (prefix, name) if prefix else name
        return self._views_root + vn

    def index_views(self, request):
        """
        首页
        :param request:
        :return:
        """
        return HttpResponseRedirect(reverse(self.content_views))

    def category_views(self, request):
        """
        栏目清单页面
        :param request:
        :return:
        """
        return render_to_response(self.get_views_name("category.html"))

    def category_editor_views(self, request):
        """
        栏目编辑页面（添加，或更新）
        :param request:
        :return:
        """
        pass

    def content_views(self, request):
        """
        内容清单页面
        :param request:
        :return:
        """
        return render_to_response(self.get_views_name("content.html"))

    def content_editor_views(self, request):
        """
        内容管理页面（添加，或更新）
        :param request:
        :return:
        """
        ctx = None
        query = request.GET
        if "token" in query:
            token = query["token"]
            from wanplus.wangwangba.models import WangwangbaContent, WangwangbaMedia
            try:
                content_model = WangwangbaContent.objects.get(token=token)
                ctx = dict()
                ctx["content"] = {
                    "title": content_model.content_name,
                    "type": content_model.content_type,
                    "coverurl": content_model.cover_url,
                    "token": token,
                }
                if content_model.content_type == int(CONTENT_TYPE_P):
                    media_token_list = content_model.data.split(",")
                    ctx["content"]["image"] = media_token_list[0]
                    page_content_token = media_token_list[1]
                    page_content_model = WangwangbaMedia.objects.get(token=page_content_token)
                    if os.path.exists(page_content_model.local_name):
                        page_content_data = None
                        file_obj = open(page_content_model.local_name, 'r')
                        try:
                            page_content_data = file_obj.read()
                            file_obj.close()
                        except Exception as e:
                            file_obj.close()
                        if page_content_data:
                            ctx["content"]["pages"] = json.loads(page_content_data, encoding='utf8')
                            ctx["content"]["pagedatafile"] = page_content_token
                elif content_model.content_type == int(CONTENT_TYPE_VIDEO):
                    ctx["content"]["video"] = content_model.data

            except WangwangbaContent.DoesNotExist as e:
                pass

        return render_to_response(self.get_views_name("content_editor.html"), context=ctx,
                                  context_instance=RequestContext(request))

    def content_save(self, request):
        return send_ok_response_with_data(data={
            "savePath": "xxx/xxx"
        })

    def layout_views(self, request):
        """
        编排页面
        :param request:
        :return:
        """
        from wanplus.wangwangba.models import WangwangbaCategory
        category_list = []
        try:
            qs = WangwangbaCategory.objects.filter(is_invalid=False)
            for item in qs:
                category_list.append({
                    "code": item.code,
                    "name": item.name
                })
        except Exception as e:
            pass
        context = {
            "categorys": category_list
        }
        return render_to_response(self.get_views_name("layout.html"), context=context)

    def get_layout_list(self, request):
        from wanplus.wangwangba.models import WangwangbaContent
        try:
            qs = WangwangbaContent.objects.order_by("-id").filter(is_invalid=False)
            result_list = list()
            for item in qs:
                o = dict()
                o["code"] = item.content_code
                o["name"] = item.content_name
                o["state"] = item.content_state
                o["category"] = item.category.code
                o["token"] = item.token

                result_list.append(o)

            return send_ok_response_with_data(data={
                "list": result_list
            })
        except Exception as e:
            return send_error_response_with_message(message=e.message)

    @require_params(["layout[]"], method="POST")
    def save_layout(self, request):
        body = request.POST
        layout_data_list = body.getlist("layout[]")
        from wanplus.wangwangba.models import WangwangbaContent, WangwangbaCategory
        try:
            for data_item in layout_data_list:
                data_obj = json.loads(data_item, encoding='utf8')
                category_code = data_obj["category"]
                content_model = WangwangbaContent.objects.get(token=data_obj["token"])
                content_model.category = WangwangbaCategory.objects.get(code=category_code)
                content_model.is_recommend = category_code is RECOMMEND_CATEGORY_CODE
                content_model.save()
            return send_ok_response_with_data(data={
                "saveOk": True
            })
        except Exception as e:
            return send_error_response_with_message("保存编排数据失败 %s" % e.message)

    def recommend_views(self, request):
        """
        推荐页面
        :param request:
        :return:
        """
        return render_to_response(self.get_views_name("recommend.html"))

    def recommend_list(self, request):
        """
        推荐列表
        :param request:
        :return:
        """
        list_data = [
            {

            }, {

            }, {

            }, {

            }
        ]
        return send_ok_response_with_data(data={
            "list": list_data
        })

    def save_cover(self, request):
        form_file = request.FILES
        file_object = form_file["file"]
        fn = file_object.name
        suffix = fn.split(".")[1]
        timestamp = time.time()
        md5 = hashlib.md5()
        md5.update("{}{}".format(fn.encode("utf8"), timestamp))
        file_name_encode = md5.hexdigest()
        result, file_name, local_name = utils.upload_file(file_object, file_name=file_name_encode,
                                                          file_suffix=suffix, root_dir="wangwangba/covers")

        from models import WangwangbaCover
        try:
            cover_model = WangwangbaCover()
            cover_model.token = file_name_encode
            cover_model.mime_type = "image/" + suffix
            cover_model.local_name = local_name
            cover_model.relate_name = file_name
            cover_model.save()
        except WangwangbaCover.DoesNotExist as e:
            pass

        from wanbatvcom.settings import MEDIA_URL
        if result:
            return send_ok_response_with_data(data={
                "filename": MEDIA_URL + file_name,  # /media/[root_dir]/[token].[png|jpg]
                "token": file_name_encode
            })
        else:
            return send_error_response_with_message(message=u'保存文件失败')

    def save_video(self, request):
        form_file = request.FILES
        file_object = form_file["file"]
        fn = file_object.name
        suffix = fn.split(".")[1]
        timestamp = time.time()
        md5 = hashlib.md5()
        md5.update("{}{}".format(fn.encode("utf8"), timestamp))
        file_name_encode = md5.hexdigest()
        base_path = "wangwangba/videos"
        result, file_name, local_name = utils.upload_file(file_object,
                                                          file_name=file_name_encode,
                                                          file_suffix=suffix,
                                                          root_dir=base_path,
                                                          mode="wb")

        from wanbatvcom.settings import MEDIA_ROOT
        upload_ok, msg = utils.upload_to_ftp(file_name_encode + "." + suffix,
                                             src_path=MEDIA_ROOT + "/" + base_path,
                                             dest_path=base_path,
                                             host="upload.sihuacdn.com",
                                             user="wanbatv",
                                             password="wanbatv_upload")

        if not upload_ok:
            return send_error_response_with_message(message=u'上传文件失败 %s' % msg)

        if os.path.exists(local_name):
            os.remove(local_name)

        from models import WangwangbaMedia
        try:
            media_model, created = WangwangbaMedia.objects.get_or_create(token=file_name_encode)
            media_model.mime_type = "video/" + suffix
            # 视频只保存在CDN，不保存在服务器，以免占用过多资源空间
            media_model.local_name = ''
            media_model.relate_name = ''
            media_model.remote_name = "/" + msg
            media_model.save()
        except Exception as e:
            return send_error_response_with_message(message=str(e))

        if result:
            return send_ok_response_with_data(data={
                "filename": "/" + msg,
                "token": file_name_encode
            })
        else:
            return send_error_response_with_message(message=u'保存文件失败')

    def save_image(self, request):
        form_file = request.FILES
        file_object = form_file["file"]
        fn = file_object.name
        suffix = fn.split(".")[1]
        timestamp = time.time()
        md5 = hashlib.md5()
        md5.update("{}{}".format(fn.encode("utf8"), timestamp))
        file_name_encode = md5.hexdigest()
        result, file_name, local_name = utils.upload_file(file_object, file_name=file_name_encode,
                                                          file_suffix=suffix, root_dir="wangwangba/images")

        from models import WangwangbaMedia
        try:
            media_model = WangwangbaMedia()
            media_model.token = file_name_encode
            media_model.mime_type = "image/" + suffix
            media_model.local_name = local_name
            media_model.relate_name = file_name
            media_model.save()
        except WangwangbaMedia.DoesNotExist as e:
            pass

        from wanbatvcom.settings import MEDIA_URL
        if result:
            return send_ok_response_with_data(data={
                "filename": MEDIA_URL + file_name,  # /media/[root_dir]/[token].[png|jpg]
                "token": file_name_encode
            })
        else:
            return send_error_response_with_message(message=u'保存文件失败')

    def save_text(self, title, content, fn=None):

        if not fn:
            timestamp = time.time()
            md5 = hashlib.md5()
            md5.update("{}{}".format(title.encode("utf8"), timestamp))
            fn = md5.hexdigest()

        result, filename, local_name = utils.save_text_to_file(content, file_name=fn,
                                                               file_suffix="wbt",
                                                               root_dir="wangwangba/files",
                                                               mode="w")

        from models import WangwangbaMedia
        try:
            media_model, created = WangwangbaMedia.objects.get_or_create(token=fn)
            media_model.mime_type = "text/plain"
            media_model.local_name = local_name
            media_model.relate_name = filename
            media_model.save()
        except WangwangbaMedia.DoesNotExist as e:
            pass

        if result:
            return result, fn
        else:
            return result, u'保存文件失败'

    def dogtv_view(self, request):
        from wanplus import config
        context = {
            "api": {
                "preview_host": config.PREVIEW_HOST,
                "release_host": config.RELEASE_HOST
            }
        }
        return render_to_response(self.get_views_name("dogtv.html"), context=context)

    @require_params(["covers[]", "remotehost"], method="post")
    def dogtv_sync_cover_to_api(self, request):

        body = request.POST.copy()
        covers = body.getlist("covers[]")
        remote_host = body["remotehost"]
        local_host = request.get_host()

        import urllib2
        import urllib
        post_data = {
            "covers": ",".join(covers),
            "srchost": local_host
        }
        req = urllib2.Request("http://121.201.14.248:8062/api/wangwangba/synccover", urllib.urlencode(post_data))
        req.add_header("Content-Type", "application/x-www-form-urlencoded")
        res = urllib2.urlopen(req)
        result_data = res.read()
        res.close()

        return send_response_with_result(json.dumps(result_data))

    def save_dogtv_cover(self, request, position):
        response = self.save_cover(request)
        save_result = json.loads(response.content, encoding='utf8')
        if "data" not in save_result:
            return response

        save_res_data = save_result["data"]
        position = int(position)
        filename = save_res_data["filename"]
        token = save_res_data["token"]

        from wanplus.wangwangba.models import WangwangbaDogtvCovers
        try:
            obj, create = WangwangbaDogtvCovers.objects.get_or_create(position=position)
            obj.filename = filename
            obj.token = token
            obj.save()
        except Exception as e:
            return send_error_response_with_message(message=e.message)

        return send_ok_response_with_data(data={
            "position": position,
            "filename": filename,
            "token": token
        })

    def save_content_cover(self, request):
        return self.save_cover(request)

    def save_content_video(self, request):
        return self.save_video(request)

    def save_content_image(self, request):
        return self.save_image(request)

    @require_params(["title", "coverurl", "type"], method="POST")
    def save_content(self, request):

        def generate_code(id, type, token):
            return '%s%08d%s' % (type, id, token[-4:])

        def handle_video_content(bd):
            return bd["video"] if "video" in bd else ''

        def handle_p_content(bd):
            d = ''
            if 'image' in bd:
                d += bd["image"]
            d += ','
            if 'pages[]' in bd:
                fn = None
                if "datafile" in bd:
                    fn = bd["datafile"]
                page_list = bd.getlist("pages[]")
                temp_list = []
                for page_item in page_list:
                    temp_item = json.loads(page_item, encoding='utf8')
                    ic = temp_item["content"]
                    temp_list.append(temp_item)
                success, msg = self.save_text(bd["title"], json.dumps(temp_list), fn=fn)
                if success:
                    d += msg
                else:
                    raise RuntimeError("保存分页内容失败")
            return d

        def handle_sale_content(db):
            return ''

        handler = dict()
        handler[CONTENT_TYPE_VIDEO] = handle_video_content
        handler[CONTENT_TYPE_P] = handle_p_content
        handler[CONTENT_TYPE_SALE] = handle_sale_content

        body = request.POST
        title = body["title"]
        t = body["type"]
        content_type = int(t)
        cover_url = body["coverurl"]
        timestamp = time.time()
        now = datetime.datetime.now()
        md5 = hashlib.md5()
        md5.update("{}{}{}".format(title.encode("utf8"), timestamp, content_type))
        token = md5.hexdigest()

        from wanplus.wangwangba.models import WangwangbaContent
        try:
            if "token" not in body:  # 新建
                content_model = WangwangbaContent()
                content_model.token = token
                content_model.content_name = title
                content_model.content_type = content_type
                content_model.content_state = CONTENT_STATE_NO_SYNC
                content_model.category = self._category_list[0]
                content_model.date_added = now
                content_model.date_last = now
                content_model.cover_url = cover_url
                content_model.data = handler[t](body)
                content_model.save()
                content_model.content_code = generate_code(content_model.id, content_type, token)
                content_model.save()
            else:  # 更新
                content_model = WangwangbaContent.objects.get(token=body["token"])
                content_model.content_name = title
                content_model.content_type = content_type
                content_model.content_state = CONTENT_STATE_NO_SYNC
                content_model.date_last = now
                content_model.cover_url = cover_url
                content_model.data = handler[t](body)
                content_model.save()

            return send_ok_response_with_data(data={
                "token": token
            })
        except Exception as e:
            return send_error_response_with_message(message=str(e))

    def get_content_list(self, request):
        from wanplus.wangwangba.models import WangwangbaContent
        try:
            qs = WangwangbaContent.objects.order_by("-id").filter(is_invalid=False)
            result_list = list()
            for item in qs:
                o = dict()
                o["code"] = item.content_code
                o["name"] = item.content_name
                o["type"] = item.content_type
                o["state"] = item.content_state
                o["category"] = item.category.name
                o["recommend"] = item.is_recommend
                o["token"] = item.token

                result_list.append(o)

            return send_ok_response_with_data(data={
                "list": result_list
            })
        except Exception as e:
            return send_error_response_with_message(message=e.message)

    def _sync_content(self, request, host, content_token=None):

        from wanplus.wangwangba.models import WangwangbaContent, WangwangbaMedia
        content = None
        try:
            content = WangwangbaContent.objects.get(token=content_token)
        except Exception as e:
            return send_error_response_with_message(message=str(e))

        if not content:
            return send_error_response_with_message(message='无此 %s 的内容' % content_token)

        sync_url = 'http://%s/api/wangwangba/synccontent/%s' % (host, content.category.code)

        content_type = content.content_type

        data = {
            "token": content.token,
            "title": content.content_name.encode(encoding="utf8"),
            "coverpath": content.cover_url,
            "srchost": request.get_host(),
            "contenttype": content_type,
        }

        if content_type == 1:
            try:
                media = WangwangbaMedia.objects.get(token=content.data)
                data["videourl"] = media.remote_name
            except Exception as e:
                return send_error_response_with_message(message=str(e))
        elif content_type == 2:
            if content.data:
                try:
                    content_datas = content.data.split(",")
                    data_len = len(content_datas) if content_datas else 0
                    if data_len:
                        from wanbatvcom.settings import MEDIA_URL
                        image = WangwangbaMedia.objects.get(token=content_datas[0])
                        data["imageurl"] = MEDIA_URL + image.relate_name
                    if data_len > 1:
                        file_model = WangwangbaMedia.objects.get(token=content_datas[1])
                        file_handler = open(file_model.local_name, 'r')
                        data["content"] = file_handler.read()
                        file_handler.close()
                except Exception as e:
                    return send_error_response_with_message(message=str(e))

        import urllib
        import urllib2

        try:
            import logging
            logger = logging.getLogger('wanba')
            logger.info("post data %s" % json.dumps(data, encoding='utf8'))
            request = urllib2.Request(sync_url, urllib.urlencode(data))
            request.add_header("Content-Type", "application/x-www-form-urlencoded")
            response = urllib2.urlopen(request)
            sync_result = response.read()
            response.close()
        except Exception as e:
            return send_error_response_with_message(message=str(e))

        if host is config.PREVIEW_HOST:
            content.content_state = CONTENT_STATE_PREVIEW
            content.save()
        elif host is config.RELEASE_HOST:
            content.content_state = CONTENT_STATE_RELEASE
            content.save()

        return send_response_with_result(sync_result)

    def sync_content_preview(self, request, content_token=None):
        return self._sync_content(request, config.PREVIEW_HOST, content_token)

    def sync_content_release(self, request, content_token=None):
        return self._sync_content(request, config.RELEASE_HOST, content_token)

    def save_journal(self, request):
        pass

    def _sync_journal(self, request, host, journal_token=None):
        pass

    def sync_journal_preview(self, request, journal_token=None):
        return self._sync_journal(request, config.PREVIEW_HOST, journal_token)

    def sync_journal_release(self, request, journal_token=None):
        return self._sync_journal(request, config.RELEASE_HOST, journal_token)

    def trailer_views(self, request):
        return render_to_response(self.get_views_name("trailer.html"))

    def get_dogtv_program_list(self, request):
        try:
            queryset = WangwangbaDogtvProgram.objects.\
                values("token", "name", "url", "is_trailer").all()
            if queryset.exists():
                dogtv_list = list()
                for dogtv_item in queryset:
                    dogtv_list.append(dogtv_item)
                return send_ok_response_with_list(dogtv_list)
        except Exception as e:
            return send_error_response_on_exception(e)

        return send_ok_response_with_list([])

    def get_trailer_info(self, request):
        """
        获取 trailer 的标题和封面
        :param request:
        :return:
        """
        from wanplus.wangwangba.models import WangwangbaSettings
        trailer_info = WangwangbaSettings.value_of("trailer")
        if trailer_info:
            return send_ok_response_with_data(trailer_info)
        else:
            return send_ok_response_with_data({})

    def _sync_trailer(self, request, host):
        body = request.POST
        trailer_info = {
            "title": body["title"],
            "cover": body["cover"]
        }
        from wanplus.wangwangba.models import WangwangbaSettings
        WangwangbaSettings.value_of("trailer", value=trailer_info)

        tokens = body["tokens"]
        if tokens:
            token_list = tokens.split(",")
            queryset = WangwangbaDogtvProgram.objects.all()
            if queryset.exists() and token_list:
                for model in queryset:
                    model.is_trailer = model.token in token_list
                    model.save()

        return send_ok_response_with_data(request.POST)

    @require_params(["title", "cover", "tokens"], method='POST')
    def sync_trailer_preview(self, request):
        return self._sync_trailer(request, config.PREVIEW_HOST)

    @require_params(["title", "cover", "tokens"], method='POST')
    def sync_trailer_release(self, request):
        return self._sync_trailer(request, config.RELEASE_HOST)

    @require_params(["url"], method='POST')
    def encrypt_url(self, request):
        md5 = hashlib.md5()
        auth_time = hex(int(time.time() / 1000))
        md5.update("w2nBa7VS1" + request.POST["url"] + auth_time)
        auth_token = md5.hexdigest()
        return send_ok_response_with_data({
            "token": auth_token,
            "time": auth_time
        })

    def save_trailer_cover(self, request):
        return self.save_cover(request)


content_service = WangwangbaContentService()
